#include "Console.h"

namespace ConsoleDebug
{

	//bool MByteToWChar(LPCSTR lpcszStr, std::wstring& wString)
	//{
	//	std::wstring sss = L"";
	//	DWORD dwMinSize;
	//	LPWSTR lpwszStr = NULL;
	//	dwMinSize = MultiByteToWideChar (CP_ACP, 0, lpcszStr, -1, NULL, 0);
	//	lpwszStr = new WCHAR[dwMinSize];
	//	MultiByteToWideChar (CP_ACP, 0, lpcszStr, -1, lpwszStr, dwMinSize);  
	//	wString.assign(lpwszStr);
	//	delete [] lpwszStr;
	//	return true;
	//}

	DXConsole::DXConsole(void) :
	m_nNowHeight(0)
	{

	}

	DXConsole::~DXConsole(void)
	{
		ClearOutput();
	}

	void DXConsole :: ClearOutput(void)
	{
		m_nNowHeight = 0;
		for(int i=0; i<m_strOutput.size();i++)
		{
			delete m_strOutput[i];
		}
		m_strOutput.clear();
	}

	void DXConsole :: Render(IDirect3DDevice9*  pd3dDevice, float ftime)
	{

		
		int limit_height = m_nHeight - m_nFontHeight;
		//RECT rectFull = {0, 0, m_nWidth, m_nHeight};
		pd3dDevice->BeginScene();

		RenderBackground();

		m_pSprite->Begin(D3DXSPRITE_SORT_TEXTURE|D3DXSPRITE_ALPHABLEND);

		RenderInput(ftime);
		
		
		int size = m_strOutput.size() - 1;
		//char buffer[4096];
		//sprintf_s(buffer,4096,"m_nScrolltype = %d\n",m_nScrolltype);
		if(m_nScrolltype == CONSOLE_SCROLL_UP)
		{
			int base = limit_height;
			RECT outRect = {0, base, m_nWidth, m_nHeight};
			
			
			//sprintf_s(buffer,4096,"limit_height = %d\n",limit_height);
			//OutputDebugString(buffer);

			//sprintf_s(buffer,4096,"m_nWidth = %d\n",m_nWidth);
			//OutputDebugString(buffer);

			//sprintf_s(buffer,4096,"m_nWidth = %d\n",m_nHeight);
			//OutputDebugString(buffer);

			//sprintf_s(buffer,4096,"size = %d\n",size);
			//OutputDebugString(buffer);

			//sprintf_s(buffer,4096,"m_nMaxDisplayLines = %d\n",m_nMaxDisplayLines);
			//OutputDebugString(buffer);
			//OutputDebugString("------------------------\n");

			for(int i = size; i>=0; i--)
			{
				if( m_nMaxDisplayLines == size - i )
					break;

				tConsoleRecod* output = m_strOutput[i];

				base -= output->m_nHeight;

				outRect.top = base;

				m_pFont->DrawTextW(m_pSprite,
					output->m_strMessage.c_str(),
					-1,
					&outRect,
					DT_SINGLELINE | DT_NOCLIP | m_hAnchor,
					output->m_nFlag);

				if(base < 0)
					break;
			}
		}
		else
		{
			int base = 0;
			RECT outRect = {0, base, m_nWidth, m_nHeight};
			
			for(int i = size; i>=0; i--)
			{
				tConsoleRecod* output = m_strOutput[i];

				if( base + output->m_nHeight > limit_height ||
					m_nMaxDisplayLines == size - i)
					break;

				outRect.top = base;

				m_pFont->DrawTextW(m_pSprite,
					output->m_strMessage.c_str(),
					-1,
					&outRect,
					DT_SINGLELINE | DT_NOCLIP | m_hAnchor,
					output->m_nFlag);

				base += output->m_nHeight;
			}
		}

		m_pSprite->End();
		pd3dDevice->EndScene();
	}

	int DXConsole :: GetWordWidth(WCHAR w)
	{
		std::map<WCHAR,int>::iterator iter = m_nWordWidthMap.find(w);
		int width = 0;
		if(iter == m_nWordWidthMap.end())
		{
			WCHAR wszWord[] = {w,0};
			RECT testRect = {0, 0, m_nWidth, m_nHeight};
			m_pFont->DrawTextW(NULL,
				wszWord,
				-1,
				&testRect,
				DT_CALCRECT | DT_SINGLELINE,
				D3DXCOLOR( 1.0f, 0.0f, 0.0f, 1.0f ) );

			width = testRect.right;
			m_nWordWidthMap[w] = width;
		}
		else
		{
			width = iter->second;
		}


		return width;
	}

	void DXConsole :: Output(std::wstring wsz_full_buffer, D3DXCOLOR color)
	{
		if(!m_bInit)
			return;

		RECT testRect = {0, 0, m_nWidth, m_nHeight};
		int current_line_width = 0;
		bool line_break = false;
		int start_offset = 1;
		int count_offset = 0;
		int start = 0;
		int count = 1;
		int end = 0;
		int ScreenLimit = m_nHeight - m_nFontHeight * 2;
		int string_size = wsz_full_buffer.size();

		//sprintf_s(buffer,4096,"string_size = %d\n",string_size);
		//OutputDebugString(buffer);

		for(int i=0;i<string_size;i++)
		{
			WCHAR w = wsz_full_buffer[i];
			if( w == L'\n' || w == L'\r')
			{
				current_line_width = 0;
				line_break = true;
				start_offset = 1;
				count_offset = 1;
			}
			else
			{
				int wword = GetWordWidth(w);
				current_line_width += wword;

				if(current_line_width > m_nWidth - m_nFontHeight)
				{
					current_line_width = 0;
					line_break = true;
					count_offset = 1;
				}
				/*
				else if(i == string_size - 1)
				{
					current_line_width = 0;
					line_break = true;
					count_offset = 0;
				}
				*/

				start_offset = 0;
			}

			if(line_break)
			{
				if(m_nNowHeight > ScreenLimit)
				{
					m_nNowHeight -= m_nFontHeight;
					tConsoleRecod* output = *(m_strOutput.begin());
					delete output;
					m_strOutput.erase(m_strOutput.begin());
				}
				
				tConsoleRecod* pData = new tConsoleRecod( wsz_full_buffer.substr(max(start,0),i - start).c_str(),
														  m_nFontHeight,
										                  color );

				m_strOutput.push_back(pData);

				//sprintf_s(buffer,4096,"push_back = %d\n",0);
				//OutputDebugString(buffer);
				m_nNowHeight += m_nFontHeight;

				count = 1 + count_offset;
				start = i + start_offset;
				line_break = false;
		   }
		   else
		   {
				count++;
		   }
		}

		tConsoleRecod* pData = new tConsoleRecod( wsz_full_buffer.substr(max(start,0),string_size - start).c_str(),
			m_nFontHeight,
			color );
		m_strOutput.push_back(pData);

		//sprintf_s(buffer,4096,"push_back = %d\n",1);
		//OutputDebugString(buffer);
		//OutputDebugString("--------------------\n");
		/*
		m_pFont->DrawTextW(NULL,
			pRecord->m_strMessage.c_str(),
			-1,
			&testRect,
			DT_CALCRECT | DT_WORDBREAK,
			D3DXCOLOR( 1.0f, 0.0f, 0.0f, 1.0f ) );
		*/

		//if(m_nNowHeight > m_nHeight - m_nFontHeight)
		//{
		//	//m_outputHeights.erase(m_outputHeights.begin());
		//	tConsoleRecod* output = *(m_strOutput.begin());

		//	m_nNowHeight -= output->m_nHeight;
		//	delete output;
		//	m_strOutput.erase(m_strOutput.begin());
		//}


		//pRecord->m_nHeight = testRect.bottom;
		//pRecord->m_nFlag = nFlag;

		//m_strOutput.push_back(pRecord);
		//m_nNowHeight += testRect.bottom;
	}
	void DXConsole :: Output(const char* szBuffer, D3DXCOLOR color)
	{
		//char buffer[4096];
		//sprintf_s(buffer,4096,"m_bInit = %d\n",m_bInit);
		//OutputDebugString(buffer);
		if(!m_bInit)
			return;
		std::wstring wsz_full_buffer;
		MByteToWChar(szBuffer,wsz_full_buffer);
		Output(wsz_full_buffer,color);
	}

	
};
